﻿#region USING
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Security.Cryptography;
using System.Configuration;
using System.Data;
#endregion

namespace GeneralClasses
{

    /// <summary>
    /// a abstract class that has a lot of useful functions that most of the other classes will commonly use
    /// </summary>
    public abstract class UTIL
    {
        #region DATABASE
        /// <summary>
        /// give a department to all the persons without one
        /// </summary>
        public static void fixDepartments()
        {
            try
            {
                //new database connection
                DatabaseConnection dbc = new DatabaseConnection();

                //find the first paygrade by default
                DataTable table = dbc.query("SELECT deid FROM Department");
                int firstDepartmentID = -1;

                if ((table != null) && (table.Rows.Count > 0))
                {
                    foreach (DataRow row in table.Rows)
                    {
                        firstDepartmentID = (int)row["deid"];
                        break;
                    }
                }
                if (firstDepartmentID != -1)
                {
                    //get all the persons without paygrades
                    table = dbc.query("SELECT DISTINCT Person.perid FROM Person, personhasdepartmentrelationship WHERE personhasdepartmentrelationship.perid  NOT IN (Person.perid)");
                    List<int> personTableIDs = new List<int>();
                    if ((table != null) && (table.Rows.Count > 0))
                    {
                        foreach (DataRow row in table.Rows)
                        {
                            personTableIDs.Add((int)row["perid"]);
                        }
                    }
                    foreach (int ID in personTableIDs)
                    {
                        dbc.executeNonQuery("INSERT INTO personhasdepartmentrelationship (perid, deid) values ('" + ID + "','1'");
                    }
                }
                if (firstDepartmentID != -1)
                {
                    //get all the persons without paygrades
                    table = dbc.query("SELECT DISTINCT Person.perid FROM Person, personhaspreferreddepartmentrelationship WHERE personhaspreferreddepartmentrelationship.perid  NOT IN (Person.perid)");
                    List<int> personTableIDs = new List<int>();
                    if ((table != null) && (table.Rows.Count > 0))
                    {
                        foreach (DataRow row in table.Rows)
                        {
                            personTableIDs.Add((int)row["perid"]);
                        }
                    }
                    foreach (int ID in personTableIDs)
                    {
                        dbc.executeNonQuery("INSERT INTO personhaspreferreddepartmentrelationship (perid, deid) values ('" + ID + "','1'");
                    }
                }
            }
            catch (Exception e)
            {
                UTIL.sayDebug(e);
                throw e;
            }
        }

        /// <summary>
        /// give a paygrade to all the persons without one
        /// </summary>
        public static void fixPaygadeRelationships()
        {
            try
            {
                //give a paygrade to all the persons without one

                //new database connection
                DatabaseConnection dbc = new DatabaseConnection();

                //find the first paygrade by default
                DataTable table = dbc.query("SELECT paid FROM Paygrade");
                int firstPaygrade = -1;

                if ((table != null) && (table.Rows.Count > 0))
                {
                    foreach (DataRow row in table.Rows)
                    {
                        firstPaygrade = (int)row["paid"];
                        break;
                    }
                }
                if (firstPaygrade != -1)
                {
                    //get all the persons without paygrades
                    table = dbc.query("SELECT DISTINCT Person.perid FROM Person, personhaspaygraderelationship WHERE personhaspaygraderelationship.perid  NOT IN (Person.perid)");
                    List<int> personTableIDs = new List<int>();
                    if ((table != null) && (table.Rows.Count > 0))
                    {
                        foreach (DataRow row in table.Rows)
                        {
                            personTableIDs.Add((int)row["perid"]);
                        }
                    }
                    foreach (int ID in personTableIDs)
                    {
                        dbc.executeNonQuery("INSERT INTO personhaspaygraderelationship (perid, paid) values ('" + ID + "','1'");
                    }
                }
            }
            catch (Exception e)
            {
                UTIL.sayDebug(e);
                throw e;
            }
        }

        /// <summary>
        /// goes through the database and tries fixing the holes with the first option it can find. 
        /// </summary>
        public static void fixDatabase()
        {
            fixPaygadeRelationships();
            fixDepartments();
        }

        public static bool isStringSafeFromSQLInjection(String str)
        {
            #region old
            //check for any asterixes in the array
            //char[] chararray = str.ToCharArray();
            /*for (int i = 0; i <= chararray.Length - 1; i++)            {
                if (chararray[i].CompareTo('*') == 0) return false;          }*/
            //Regex semicolonPattern = new Regex("*;*");
            //Regex percentPattern = new Regex("*%*");
            //if (semicolonPattern.IsMatch(str)) return false;
            //if (percentPattern.IsMatch(str)) return false;
            #endregion

            if (str.ToLower().Contains("drop")) return false;
            else if (str.ToLower().Contains("*")) return false;
            else if (str.ToLower().Contains("%")) return false;
            else if (str.ToLower().Contains("=")) return false;
            else if (str.ToLower().Contains("force")) return false;
            else if (str.ToLower().Contains("null")) return false;
            else if (str.ToLower().Contains("--")) return false;
            else if (str.ToLower().Contains(@"\")) return false;
            else if (str.ToLower().Contains("_")) return false;
            else if (str.ToLower().Contains("xp")) return false;
            else if (str.ToLower().Contains("[")) return false;
            else if (str.ToLower().Contains("]")) return false;

            else return true;
        }


        /// <summary>
        /// returns the bit string from the MD5 hashing. This hash and the stored one from the database are to be compared.
        /// <param name="milliseconds"></param>
        public static String MD5Hasher(String password)
        {
            System.Security.Cryptography.MD5CryptoServiceProvider x = new System.Security.Cryptography.MD5CryptoServiceProvider();
            byte[] data = System.Text.Encoding.ASCII.GetBytes(password);
            data = x.ComputeHash(data);
            string ret = "";
            for (int i = 0; i < data.Length; i++)
                ret += data[i].ToString("x2").ToLower();
            return ret;
        }


        #endregion


        /// <summary>
        /// delays whatever you are doing for a give amount of time
        /// </summary>
        /// <param name="milliseconds"></param>
        public static void delay(long milliseconds)
        {
            ///delays the process intentionally, might come in handy
            System.Threading.Thread.Sleep((int)milliseconds);
        }


        #region SAY
        //prints out a message to the console
        public static void say(String s)
        {
            s = s.Trim();
            System.Console.WriteLine(s);
        }
        public static void say(String s, int x)
        {
            s = s.Trim();
            for (int i = x; i <= 0; i++)
            {
                //Console.Write("   ");
                s = "___" + s;
            }
            System.Console.WriteLine(s);
        }
        public static void say(int l, String s, int x)
        {
            for (int i = l; i > 0; i--)
            {
                Console.Write("\n");
            }
            s = s.Trim();
            for (int i = x; i <= 0; i++)
            {
                s = "___" + s;
                //Console.Write("_  ");
            }
            Console.WriteLine(s);
        }
        public static void say(int l, String s)
        {
            for (int i = l; i > 0; i--)
            {
                Console.Write("\n");
            }
            s = s.Trim();
            Console.WriteLine(s);
        }

        public static void sayDebug(Exception e)
        {
            System.Diagnostics.Debug.WriteLine(">> DEBUG:   " + (e.Message));
            System.Diagnostics.Debug.WriteLine(">> DEBUG:   " + (e.StackTrace));
        }

        public static void sayDebug(String msg)
        {
            System.Diagnostics.Debug.WriteLine(">> DEBUG:   " + msg);
        }

        public static void sayDebugStackTrace(Exception e)
        {
            System.Diagnostics.Debug.WriteLine(">> DEBUG:   " + (e.StackTrace.Trim()));
        }



        //prints an error message to the console. this was more useful in java than it is here
        public static void sayError(String s)
        {
            s = s.Trim().ToUpper();
            Console.WriteLine("\nERROR: " + s);
        }

        #endregion



        public static void saveExceptionToFile(Exception e)
        {
            String filename = "exceptions\\Exception_(" + DateTime.Now + ")_" + e.Message.Substring(0, 16) + ".txt";
            List<String> stuffToWrite = new List<String>();
            stuffToWrite.Add(e.Message);
            stuffToWrite.Add(e.Source);
            stuffToWrite.Add(e.TargetSite.ToString());
            stuffToWrite.Add(e.StackTrace);
            stuffToWrite.Add(e.HelpLink);
            stuffToWrite.Add("\n");
            if (e.InnerException != null)
            {
                stuffToWrite.Add(e.InnerException.Message);
            }
            FileDealer.writeFile(filename, stuffToWrite);
        }

        public static int boolToInt(bool b)
        {
            if (b == true)
                return 1;
            else
                return 0;
        }

        public static string personalizeScheduleText(Person person, string text)
        {
            char[] splitter = { '\n' };
            string[] lines = text.Split(splitter);
            char[] splitter2 = { '\r' };
            string[] lines2 = text.Split(splitter2);
            string newText = "";

            foreach (string line in lines)
            {
                if (line.Contains(person.Username + "  " + person.FullName))
                    newText += line + '\n';
            }

            return newText;
        }
    } // end class
}
